﻿using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HuaweiCloud.Dotnet.Samples.Common.Cache.Extension
{
    /// <summary>
    /// 封装直接获取实体的方法
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public static class IDistributedCacheExtension
    {
        /// <summary>
        /// 获取缓存(异步)
        /// </summary>
        /// <param name="key">键值</param>
        /// <param name="token">取消任务的Token</param>
        /// <returns></returns>
        public static async Task<T?> GetAsync<T>(this IDistributedCache self, string key, CancellationToken token = default) where T : class
        {
            var bs = await self.GetAsync(key, token);
            if(bs == null)
            {
                return null;
            }
            var temp = Encoding.UTF8.GetString(bs);
            return JsonConvert.DeserializeObject<T>(temp);
        }

        /// <summary>
        /// 优先获取缓存(异步) 如果没有缓存 则执行默认委托获取并将结果存入缓存中
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">键值</param>
        /// <param name="factory">默认委托</param>
        /// <param name="optionFactory">过期配置委托</param>
        /// <param name="token">取消任务的Token</param>
        /// <returns></returns>
        public static async Task<T?> GetOrDefaultAsync<T>(this IDistributedCache self, string key, Func<Task<T?>> defaultFactory,Func<DistributedCacheEntryOptions>? optionFactory = null , CancellationToken token = default) where T : class
        {
            var temp = await self.GetAsync<T>(key, token);
            temp ??= await defaultFactory();
            await self.SetAsync(key, temp, optionFactory?.Invoke(), token);
            return temp;
        }


        //Task RefreshAsync();

        /// <summary>
        /// 设置缓存(异步)
        /// </summary>
        /// <param name="key">键值</param>
        /// <param name="entity">存入实体</param>
        /// <param name="expiredTime">相对过期时间</param>
        /// <param name="token">取消任务的Token</param>
        /// <returns></returns>
        public static async Task SetAsync<T>(this IDistributedCache self, string key, T? entity, DistributedCacheEntryOptions? options, CancellationToken token = default) where T : class
        {
            var temp = JsonConvert.SerializeObject(entity);
            var bs = Encoding.UTF8.GetBytes(temp);
            await self.SetAsync(key, bs, options, default);
        }
    }
}
